@file:OptIn(ExperimentalMaterialApi::class)

package com.fanketly.accompanist.global_popup

import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import kotlinx.coroutines.CoroutineScope

///////////////////////////////////////////////////////////////////////////
// SimpleGlobalBottomSheetLayout
///////////////////////////////////////////////////////////////////////////
/**
 *一个简单的全局底部弹出框
 **/
@Composable
fun SimpleGlobalBottomSheetLayout(
    globalViewModel: SimpleGlobalBottomLayoutViewModel = viewModel(),
    sheetState: ModalBottomSheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    ),
    content: @Composable () -> Unit
) {
    LaunchedEffect(key1 = globalViewModel.isShowSheet, block = {
        if (globalViewModel.isShowSheet) sheetState.show()
        else sheetState.hide()
    })
    LaunchedEffect(key1 = sheetState.isVisible, block = {
        if (globalViewModel.isShowSheet != sheetState.isVisible) globalViewModel.sheetNot()
    })

    ModalBottomSheetLayout(sheetState = sheetState, sheetContent = {
        globalViewModel.globalSheetContentState(this)
    }, content = content)
}

open class SimpleGlobalBottomLayoutViewModel : ViewModel() {
    private val _globalSheetContentState by lazy {
        mutableStateOf<@Composable ColumnScope.() -> Unit>({})
    }
    val globalSheetContentState
        get() = _globalSheetContentState.value

    private val _showSheet = mutableStateOf(false)
    val isShowSheet
        get() = _showSheet.value

    fun closeSheet() {
        _showSheet.value = false
    }

    fun sheetNot() {
        _showSheet.value = _showSheet.value.not()
    }

    fun showSheet() {
        _showSheet.value = true
    }

    fun setSheetContent(sheetContent: @Composable ColumnScope.() -> Unit) {
        _globalSheetContentState.value = sheetContent
    }
}

///////////////////////////////////////////////////////////////////////////
// GlobalBottomSheetLayout
///////////////////////////////////////////////////////////////////////////
/**
 *  可以叠加的全局底部弹出框
 * 提示：不要忘记在 隐藏时 移除不该在下次显示的组件
 **/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun GlobalBottomSheetLayout(
    globalViewModel: GlobalBottomLayoutViewModel,
    modifier: Modifier = Modifier,
    boxModifier: Modifier = Modifier,
    sheetState: ModalBottomSheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    ),
    content: @Composable () -> Unit
) {
    LaunchedEffect(key1 = globalViewModel.isShowSheet, block = {
        if (globalViewModel.isShowSheet) sheetState.show()
        else sheetState.hide()
    })
    LaunchedEffect(key1 = sheetState.isVisible, block = {
        if (globalViewModel.isShowSheet != sheetState.isVisible) globalViewModel.sheetNot()
    })

    ModalBottomSheetLayout(modifier = modifier, sheetState = sheetState, sheetContent = {
        Box(modifier = boxModifier.defaultMinSize(minHeight = 1.dp)) {
            globalViewModel.globalSheetContentState.forEach {
                it()
            }
        }
    }, content = content)
}

open class GlobalBottomLayoutViewModel : ViewModel() {
    private val _globalSheetContentState by lazy {
        mutableStateListOf<@Composable () -> Unit>({})
    }
    val globalSheetContentState: List<@Composable () -> Unit>
        get() = _globalSheetContentState

    private val _showSheet = mutableStateOf(false)
    val isShowSheet
        get() = _showSheet.value

    /**
     *关闭动作条
     **/
    fun closeSheet() {
        _showSheet.value = false
    }

    /**
     *动作条当前状态设置反值
     **/
    fun sheetNot() {
        _showSheet.value = _showSheet.value.not()
    }

    /**
     *显示动作条
     **/
    fun showSheet() {
        _showSheet.value = true
    }

    /**
     *移除指定位置组件
     * @param index 默认为-1即为最后一个
     **/
    fun removeSheetContent(index: Int = -1) {
        if (_globalSheetContentState.size == 0) return
        if (index == -1) _globalSheetContentState.removeLast()
        else _globalSheetContentState.removeAt(index)
    }

    /**
     *移除之前的全部组件
     **/
    fun removeBeforeSheetContent() {
        _globalSheetContentState.removeRange(0, globalSheetContentState.size - 1)
    }

    /**
     *添加组件
     **/
    fun addSheetContent(sheetContent: @Composable () -> Unit) {
        _globalSheetContentState.add(sheetContent)
        showSheet()
    }
}

